#ifndef __DRV_GPIO_H__
#define __DRV_GPIO_H__

#ifdef __cplusplus
 extern "C" {
#endif 

#include "BaseTypes.h"
#include "drv_error_code.h"

/// Gpio端口对象类型
typedef struct TDrv_Gpio_PortxTag TDrv_Gpio_Portx;
struct TDrv_Gpio_PortxTag
{
    void* base_addr;       ///< 寄存器基地址
};

/// 端口对象实例
extern TDrv_Gpio_Portx g_drv_gpio_portA;
extern TDrv_Gpio_Portx g_drv_gpio_portB;
extern TDrv_Gpio_Portx g_drv_gpio_portC;
extern TDrv_Gpio_Portx g_drv_gpio_portD;
extern TDrv_Gpio_Portx g_drv_gpio_portF;

/// GPIO引脚
typedef enum
{
    kDrv_Gpio_Pin0                  = 0,
    kDrv_Gpio_Pin1                  = 1,
    kDrv_Gpio_Pin2                  = 2,
    kDrv_Gpio_Pin3                  = 3,
    kDrv_Gpio_Pin4                  = 4, 
    kDrv_Gpio_Pin5                  = 5,
    kDrv_Gpio_Pin6                  = 6,
    kDrv_Gpio_Pin7                  = 7,
    kDrv_Gpio_Pin8                  = 8,
    kDrv_Gpio_Pin9                  = 9,
    kDrv_Gpio_Pin10                 = 10,
    kDrv_Gpio_Pin11                 = 11,
    kDrv_Gpio_Pin12                 = 12,
    kDrv_Gpio_Pin13                 = 13,
    kDrv_Gpio_Pin14                 = 14,
    kDrv_Gpio_Pin15                 = 15,
    kDrv_Gpio_PinxMax
} TDrv_Gpio_Pinx;

/// GPIO引脚输出方式
typedef enum
{
    kDrv_Gpio_PushPull          = 0,    ///< 推挽输出
    kDrv_Gpio_OpenDrain         = 1,    ///< 开漏输出
    kDrv_Gpio_Output_Type_Max
} TDrv_Gpio_Output_Type;

/// GPIO引脚上拉、下拉
typedef enum
{
    kDrv_Gpio_PullNo            = 0,    ///< 无
    kDrv_Gpio_PullUp            = 1,    ///< 上拉
    kDrv_Gpio_PullDown          = 2,    ///< 下拉
    kDrv_Gpio_Pull_Max
} TDrv_Gpio_Pull;

/// GPIO引脚输出速度
typedef enum
{
    kDrv_Gpio_SpeedLow          = 0,    ///< 低速
    kDrv_Gpio_SpeedMedium       = 1,    ///< 中速
    kDrv_Gpio_SpeedHigh         = 2,    ///< 高速
    kDrv_Gpio_Speed_Max
} TDrv_Gpio_Speed;

/// GPIO引脚工作模式
typedef enum
{
    kDrv_Gpio_ModeInput         = 0,    ///< 输入模式
    kDrv_Gpio_ModeOutput        = 1,    ///< 输出模式
    kDrv_Gpio_ModeAlternate     = 2,    ///< 复用模式
    kDrv_Gpio_ModeAnalog        = 3,    ///< 模拟量输入模式
    kDrv_Gpio_Mode_Max
} TDrv_Gpio_Mode;

/// GPIO引脚复用功能枚举
typedef enum
{
    /// 不同引脚的具体复用功能需要查看芯片数据手册
    kDrv_Gpio_AF0               = 0,
    kDrv_Gpio_AF1               = 1,
    kDrv_Gpio_AF2               = 2,
    kDrv_Gpio_AF3               = 3,
    kDrv_Gpio_AF4               = 4,
    kDrv_Gpio_AF5               = 5,
    kDrv_Gpio_AF6               = 6,
    kDrv_Gpio_AF7               = 7,
    kDrv_Gpio_AF_Max
} TDrv_Gpio_Alternate;

/**
 * @brief 设置 gpiox 和 pin 表示的引脚为输入模式
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx : 参见[@TDrv_Gpio_Pinx]
 *        pull : 引脚上拉、下拉, 参见[@TDrv_Gpio_Pull]
 * @retval = 0 : 成功
 *         < 0 : 参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_InputSet(TDrv_Gpio_Portx* self, UInt32 pinx, UInt8 pull);

/**
 * @brief 设置 gpiox 和 pin 表示的引脚为输出模式
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx : 参见[@TDrv_Gpio_Pinx]
 *        type : 推挽输出、开漏输出, 参见[@TDrv_Gpio_Output_Type]
 *        pull : 引脚上拉、下拉, 参见[@TDrv_Gpio_Pull]
 *        speed : 引脚输出速度, 参见[@TDrv_Gpio_Speed]
 * @retval = 0 : 成功
 *         < 0 : 参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_OutputSet(TDrv_Gpio_Portx* self, UInt32 pinx, UInt8 type, UInt8 pull, UInt8 speed);

/**
 * @brief 设置 gpiox 和 pin 表示的引脚为复用模式
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx  : 参见[@TDrv_Gpio_Pinx]
 *        type  : 推挽输出、开漏输出, 参见[@TDrv_Gpio_Output_Type]
 *        pull  : 引脚上拉、下拉, 参见[@TDrv_Gpio_Pull]
 *        speed : 引脚输出速度, 参见[@TDrv_Gpio_Speed]
 *        af    : 复用功能，参见[@TDrv_Gpio_Alternate]
 * @retval = 0 : 成功
 *         < 0 : 参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_AlternateSet(TDrv_Gpio_Portx* self, UInt32 pinx, UInt8 type, UInt8 pull, UInt8 speed, UInt8 af);

/**
 * @brief 设置 gpiox 和 pin 表示的引脚为analog模式
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx  : 参见[@TDrv_Gpio_Pinx]
 *        pull  : 引脚上拉、下拉, 参见[@TDrv_Gpio_Pull]
 * @retval = 0 : 成功
 *         < 0 : 参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_AnalogSet(TDrv_Gpio_Portx* self, UInt32 pinx, UInt8 pull);

/**
 * @brief 获取 gpiox 和 pin 表示的引脚的工作模式
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx  : 参见[@TDrv_Gpio_Pinx]
 * @retval >= 0 : 工作模式，参见[@TDrv_Gpio_Mode]
 *         <  0 : 失败，参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_WorkMode(TDrv_Gpio_Portx* self, UInt32 pinx);

/**
 * @brief 读取 gpiox 和 pin 表示的引脚输入电平
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx : 参见[@TDrv_Gpio_Pinx]
 * @retval 0 : 低电平
 *         1 : 高电平
 *         < 0 : [@TDrv_Error_Code]
*/
Int32 Drv_Gpio_ReadPin(TDrv_Gpio_Portx* self, UInt32 pinx);

/**
 * @brief 设置 gpiox 和 pin 表示的引脚输出电平
 * @param gpiox : 端口对象, 例如: g_drv_gpio_portA
 *        pinx : 参见[@TDrv_Gpio_Pinx]
 *        en : True 引脚输出高; False 引脚输出低
 * @retval = 0 : 成功
 *         < 0 : 参见[@TDrv_Error_Code]
*/
Int32 Drv_Gpio_WritePin(TDrv_Gpio_Portx* self, UInt32 pinx, Bool en);

#ifdef __cplusplus
}
#endif

#endif /*__DRV_GPIO_H__*/
